package com.zp.controller;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.zp.annotations.AuthCheck;
import com.zp.annotations.SaSpaceCheckPermission;
import com.zp.api.aliyun.AliYunOutPaintingTask;
import com.zp.api.aliyun.domain.CreateOutPaintingTaskResponse;
import com.zp.api.aliyun.domain.GetOutPaintingTaskResponse;
import com.zp.api.imagesearch.ImageSearchFacade;
import com.zp.api.imagesearch.domain.ImageSearchResult;
import com.zp.constants.SpaceUserPermissionConstant;
import com.zp.constants.UserConstant;
import com.zp.domain.common.DeleteRequest;
import com.zp.domain.common.Result;
import com.zp.domain.entity.Picture;
import com.zp.domain.entity.Space;
import com.zp.domain.entity.User;
import com.zp.domain.request.picture.*;
import com.zp.domain.request.picture.*;
import com.zp.domain.vo.PictureTagCategory;
import com.zp.domain.vo.PictureVO;
import com.zp.enums.ErrorCode;
import com.zp.enums.PictureReviewStatusEnum;
import com.zp.exception.BusinessException;
import com.zp.manager.auth.SpaceUserAuthManager;
import com.zp.manager.auth.StpKit;
import com.zp.service.PictureService;
import com.zp.service.SpaceService;
import com.zp.service.UserService;
import com.zp.utils.ThrowUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/picture")
@Api(tags = "图片模块")
@RequiredArgsConstructor
public class PictureController {
    private final PictureService pictureService;
    private final UserService userService;
    private final SpaceService spaceService;
    private final AliYunOutPaintingTask aliYunOutPaintingTask;
    private final SpaceUserAuthManager spaceUserAuthManager;

    /**
     * 上传图片
     *
     * @param multipartFile 上传图片
     * @param uploadRequest 上传参数
     * @param request       当前登录用户
     * @return 图片信息(脱敏)
     */
    @PostMapping("/upload")
    @ApiOperation(value = "上传图片 (本地上传)")
    @ApiOperationSupport(order = 1)
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_UPLOAD)
    public Result<PictureVO> uploadPicture(@RequestPart("file") MultipartFile multipartFile, com.zp.domain.request.picture.PictureUploadRequest uploadRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(ObjUtil.isEmpty(multipartFile), ErrorCode.PARAMS_ERROR, "上传文件不能为空");
        User loginUser = userService.getLoginUser(request);
        PictureVO pictureVO = pictureService.uploadPicture(multipartFile, uploadRequest, loginUser);
        return Result.success(pictureVO);
    }

    /**
     * 上传图片(URL 上传)
     *
     * @param uploadRequest 上传参数
     * @param request       当前登录用户
     * @return 图片信息(脱敏)
     */
    @PostMapping("/upload/url")
    @ApiOperation(value = "上传图片 (URL 上传)")
    @ApiOperationSupport(order = 2)
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_UPLOAD)
    public Result<PictureVO> uploadPictureByURL(@RequestBody com.zp.domain.request.picture.PictureUploadRequest uploadRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(ObjUtil.isEmpty(uploadRequest), ErrorCode.PARAMS_ERROR, "上传文件不能为空");
        User loginUser = userService.getLoginUser(request);
        String fileUrl = uploadRequest.getFileUrl();
        PictureVO pictureVO = pictureService.uploadPicture(fileUrl, uploadRequest, loginUser);
        return Result.success(pictureVO);
    }

    /**
     * 删除图片
     *
     * @param deleteRequest id
     * @param request       当前登录用户
     * @return 删除结果
     */
    @PostMapping("/delete")
    @ApiOperation(value = "删除图片")
    @ApiOperationSupport(order = 3)
    public Result<Boolean> deletePictureById(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(deleteRequest == null || deleteRequest.getId() <= 0, ErrorCode.PARAMS_ERROR);
        // 权限校验（不依赖 Sa-Token，兼容老数据与跨源 Cookie 场景）
        User loginUser = userService.getLoginUser(request);
        Picture picture = pictureService.getById(deleteRequest.getId());
        ThrowUtils.throwIf(ObjUtil.isNull(picture), ErrorCode.NOT_FOUND_ERROR, "图片不存在");
        Space space = null;
        Long spaceId = picture.getSpaceId();
        if (spaceId != null) {
            space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
        }
        // 依据当前空间与用户身份计算权限列表
        List<String> permissionList = spaceUserAuthManager.getPermissionList(space, loginUser);
        ThrowUtils.throwIf(!permissionList.contains(SpaceUserPermissionConstant.PICTURE_DELETE), ErrorCode.NO_AUTH_ERROR, "无删除图片权限");
        // 执行删除
        pictureService.deletePicture(deleteRequest.getId(), loginUser);
        return Result.success(true);
    }

    /**
     * 更新图片
     *
     * @param pictureUpdateRequest 图片更新请求
     * @param request              当前登录用户
     * @return 更新结果
     */
    @PostMapping("/update")
    @ApiOperation(value = "编辑图片 (管理员)")
    @ApiOperationSupport(order = 9)
    @AuthCheck(requiredRole = UserConstant.ADMIN_ROLE)
    public Result<Boolean> updatePicture(@RequestBody PictureUpdateRequest pictureUpdateRequest, HttpServletRequest request) {
        if (pictureUpdateRequest == null || pictureUpdateRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Picture picture = new Picture();
        BeanUtils.copyProperties(pictureUpdateRequest, picture);
        List<String> list = pictureUpdateRequest.getTags();
        String jsonStr = JSONUtil.toJsonStr(list);
        picture.setTags(jsonStr);
        // 数据校验
        pictureService.validPicture(picture);
        Picture oldPicture = pictureService.getById(pictureUpdateRequest.getId());
        if (oldPicture == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 填充审核参数
        User loginUser = userService.getLoginUser(request);
        pictureService.fillReviewParams(picture, loginUser);
        // 执行更新
        boolean updated = pictureService.updateById(picture);
        ThrowUtils.throwIf(!updated, ErrorCode.OPERATION_ERROR);
        return Result.success(true);
    }

    /**
     * 分页获取图片列表
     *
     * @param request 查询条件
     * @return 图片列表
     */
    @PostMapping("/list/page")
    @ApiOperation(value = "分页获取图片 (管理员)")
    @ApiOperationSupport(order = 8)
    @AuthCheck(requiredRole = UserConstant.ADMIN_ROLE)
    public Result<Page<Picture>> listPictureByPage(@RequestBody PictureQueryRequest request) {
        long current = request.getCurrent();
        long pageSize = request.getPageSize();
        Page<Picture> picturePage = new Page<>(current, pageSize);
        QueryWrapper<Picture> wrapper = pictureService.getQueryWrapper(request);
        Page<Picture> page = pictureService.page(picturePage, wrapper);
        return Result.success(page);
    }

    /**
     * 根据 id 搜索图片
     *
     * @param id 图片 id
     * @return 图片信息
     */
    @GetMapping("/get")
    @ApiOperation(value = "根据 id 搜索图片 (管理员)")
    @ApiOperationSupport(order = 6)
    @AuthCheck(requiredRole = UserConstant.ADMIN_ROLE)
    public Result<Picture> getPictureById(@RequestParam("id") long id) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 查询图片是否存在
        Picture picture = pictureService.getById(id);
        if (picture == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "图片不存在");
        }
        return Result.success(picture);
    }

    /**
     * 根据 id 搜索图片
     *
     * @param id 图片 id
     * @return 图片信息
     */
    @GetMapping("/get/vo")
    @ApiOperation(value = "根据 id 搜索图片")
    @ApiOperationSupport(order = 4)
    public Result<PictureVO> getPictureVOById(@RequestParam("id") long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 查询图片是否存在
        Picture picture = pictureService.getById(id);
        if (picture == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "图片不存在");
        }
        // 空间权限校验
        Space space = null;
        Long spaceId = picture.getSpaceId();
        if (spaceId != null) {
            boolean hasPermission = StpKit.SPACE.hasPermission(SpaceUserPermissionConstant.PICTURE_VIEW);
            ThrowUtils.throwIf(!hasPermission, ErrorCode.NO_AUTH_ERROR, "无查看图片权限");
            space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
            // User loginUser = userService.getLoginUser(request);
            // pictureService.checkPictureAuth(loginUser, picture);
        }
        // 获取权限列表
        User loginUser = userService.getLoginUser(request);
        List<String> list = spaceUserAuthManager.getPermissionList(space, loginUser);
        PictureVO pictureVO = pictureService.getPictureVOWithUserVO(picture);
        pictureVO.setPermissionList(list);
        return Result.success(pictureVO);
    }

    /**
     * 分页获取图片列表
     *
     * @param queryRequest 查询条件
     * @return 图片列表
     */
    @PostMapping("/list/page/vo")
    @ApiOperation(value = "分页获取图片")
    @ApiOperationSupport(order = 5)
    public Result<Page<PictureVO>> listPictureVOByPage(@RequestBody PictureQueryRequest queryRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(queryRequest.getPageSize() > 2000, ErrorCode.PARAMS_ERROR);
        // 空间权限校验
        Long spaceId = queryRequest.getSpaceId();
        if (spaceId == null) { // 公共图库
            // 保证用户只能看到过审的图片
            queryRequest.setReviewStatus(PictureReviewStatusEnum.PASS.getValue());
            queryRequest.setNullSpaceId(true);
        } else { // 私有图库
//            User loginUser = userService.getLoginUser(request);
//            Space space = spaceService.getById(spaceId);
//            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
            boolean hasPermission = StpKit.SPACE.hasPermission(SpaceUserPermissionConstant.PICTURE_VIEW);
            ThrowUtils.throwIf(!hasPermission, ErrorCode.NO_AUTH_ERROR, "无查看图片权限");
//            if (!loginUser.getId().equals(space.getUserId())) {
//                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限操作该空间");
//            }
        }
        // 调用 Service 层使用 Redis 缓存
        Page<PictureVO> pictureVOPage = pictureService.listPictureVOByPageWithCache(queryRequest);
        return Result.success(pictureVOPage);
    }

    /**
     * 编辑图片信息
     *
     * @param pictureEditRequest 图片编辑请求
     * @param request            当前登录用户
     * @return 编辑结果
     */
    @PostMapping("/edit")
    @ApiOperation(value = "编辑图片")
    @ApiOperationSupport(order = 6)
    public Result<Boolean> editPicture(@RequestBody com.zp.domain.request.picture.PictureEditRequest pictureEditRequest, HttpServletRequest request) {
        if (pictureEditRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 权限校验（不依赖 Sa-Token，兼容老数据与跨源 Cookie 场景）
        User currentUser = userService.getLoginUser(request);
        Picture oldPicture = pictureService.getById(pictureEditRequest.getId());
        ThrowUtils.throwIf(ObjUtil.isNull(oldPicture), ErrorCode.NOT_FOUND_ERROR, "图片不存在");
        Space space = null;
        Long spaceId = oldPicture.getSpaceId();
        if (spaceId != null) {
            space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
        }
        List<String> permissionList = spaceUserAuthManager.getPermissionList(space, currentUser);
        ThrowUtils.throwIf(!permissionList.contains(SpaceUserPermissionConstant.PICTURE_EDIT), ErrorCode.NO_AUTH_ERROR, "无编辑图片权限");
        // 通过后执行业务修改
        pictureService.editPicture(pictureEditRequest, currentUser);
        return Result.success(true);
    }

    /**
     * 获取预制标签和分类
     *
     * @return 预制标签和分类
     */
    @GetMapping("/tag_category")
    @ApiOperation(value = "获取标签和分类")
    @ApiOperationSupport(order = 20)
    public Result<PictureTagCategory> listPictureTagCategory() {
        PictureTagCategory pictureTagCategory = new PictureTagCategory();
        List<String> tagList = Arrays.asList("热门", "动漫", "电脑壁纸", "手机壁纸", "艺术", "背景", "美女", "那个男人");
        List<String> categoryList = Arrays.asList("热门", "动漫", "壁纸", "校园", "艺术", "背景", "游戏", "表情包", "其他");
        pictureTagCategory.setTagList(tagList);
        pictureTagCategory.setCategoryList(categoryList);
        return Result.success(pictureTagCategory);
    }

    /**
     * 图片审核
     *
     * @param reviewRequest 图片审核请求
     * @param request       当前登录用户
     * @return 图片审核结果
     */
    @PostMapping("/review")
    @ApiOperation(value = "图片审核 (管理员)")
    @AuthCheck(requiredRole = UserConstant.ADMIN_ROLE)
    @ApiOperationSupport(order = 10)
    public Result<Boolean> doPictureReview(@RequestBody com.zp.domain.request.picture.PictureReviewRequest reviewRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(reviewRequest == null, ErrorCode.PARAMS_ERROR);
        User loginUser = userService.getLoginUser(request);
        pictureService.doPictureReview(reviewRequest, loginUser);
        return Result.success(true);
    }

    /**
     * 批量上传图片
     *
     * @param batchRequest 批量上传图片请求
     * @param request      当前登录用户
     * @return 批量上传图片数量
     */
    @PostMapping("/upload/batch")
    @AuthCheck(requiredRole = UserConstant.ADMIN_ROLE)
    @ApiOperationSupport(order = 11)
    @ApiOperation(value = "图片批量上传 (管理员)")
    public Result<Integer> uploadPictureByBatch(@RequestBody com.zp.domain.request.picture.PictureUploadByBatchRequest batchRequest, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        Integer count = pictureService.uploadPictureByBatch(batchRequest, loginUser);
        return Result.success(count);
    }

    /**
     * 以图搜图
     *
     * @param request 图片 id
     * @return 搜索成功图片 URL 列表
     */
    @PostMapping("/search/picture")
    @ApiOperation(value = "以图搜图")
    public Result<List<ImageSearchResult>> searchPictureByPicture(@RequestBody com.zp.domain.request.picture.SearchPictureByPictureRequest request) {
        ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR);
        Long pictureId = request.getPictureId();
        ThrowUtils.throwIf(pictureId == null || pictureId <= 0, ErrorCode.PARAMS_ERROR);
        Picture picture = pictureService.getById(pictureId);
        ThrowUtils.throwIf(picture == null, ErrorCode.NOT_FOUND_ERROR, "图片不存在");
        String url = picture.getUrl();
        // 以图搜图仅支持 png / jpg 格式
        if (!url.toLowerCase().endsWith(".jpg") && !url.toLowerCase().endsWith(".png") && !url.toLowerCase().endsWith(".jpeg")) {
            url = url + "?imageMogr2/format/png"; // 添加格式转换
        }
        List<ImageSearchResult> imageSearchResults = ImageSearchFacade.searchImage(url);
        return Result.success(imageSearchResults);
    }

    /**
     * 颜色搜图
     *
     * @param colorRequest 颜色搜图请求
     * @param request      当前登录用户
     * @return 搜索成功图片
     */
    @PostMapping("/search/color")
    @ApiOperation(value = "颜色搜图")
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_VIEW)
    public Result<List<PictureVO>> searchPictureByColor(@RequestBody com.zp.domain.request.picture.SearchPictureByColorRequest colorRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(colorRequest == null, ErrorCode.PARAMS_ERROR);
        String picColor = colorRequest.getPicColor();
        Long spaceId = colorRequest.getSpaceId();
        User loginUser = userService.getLoginUser(request);
        List<PictureVO> pictureVOList = pictureService.searchPictureByColor(spaceId, picColor, loginUser);
        return Result.success(pictureVOList);
    }

    /**
     * 图片批量操作
     *
     * @param batchRequest 图片批量操作请求
     * @param request      当前登录用户
     * @return 图片批量操作结果
     */
    @PostMapping("/edit/batch")
    @ApiOperation(value = "图片批量编辑")
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_EDIT)
    public Result<Boolean> editPictureByBatch(@RequestBody com.zp.domain.request.picture.PictureEditByBatchRequest batchRequest, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        pictureService.editPictureByBatch(batchRequest, loginUser);
        return Result.success(true);
    }


    /**
     * 创建 AI 扩图任务
     *
     * @param taskRequest 创建 AI 扩图任务请求
     * @param request     当前登录用户
     * @return 创建 AI 扩图任务结果
     */
    @PostMapping("/out_painting/create_task")
    @ApiOperation(value = "创建 AI 扩图任务")
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_EDIT)
    public Result<CreateOutPaintingTaskResponse> createPictureOutPaintingTask(@RequestBody CreatePictureOutPaintingTaskRequest taskRequest, HttpServletRequest request) {
        if (taskRequest == null || taskRequest.getPictureId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        CreateOutPaintingTaskResponse response = pictureService.createOutPaintingTask(taskRequest, loginUser);
        return Result.success(response);
    }


    /**
     * 查询 AI 扩图任务
     *
     * @param taskId 任务 id
     * @return AI 扩图任务
     */
    @GetMapping("/out_painting/get_task")
    @ApiOperation(value = "查询 AI 扩图任务")
    public Result<GetOutPaintingTaskResponse> getOutPaintingTask(String taskId) {
        ThrowUtils.throwIf(StrUtil.isBlank(taskId), ErrorCode.PARAMS_ERROR);
        GetOutPaintingTaskResponse response = aliYunOutPaintingTask.getOutPaintingByTaskId(taskId);
        return Result.success(response);
    }
}
